package com.lli.mc.untils;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * 二维码生成和解释工具类
 * 
 * @author lli
 *
 * @version 1.0
 *
 */
public class QrCodeUtil {

    /**
     * 
     * @description 生成二维码图片
     * @author lli
     * @create 2017年7月31日上午11:08:39
     * @version 1.0
     * @param outputStream
     *            文件输出流
     * @param content
     *            内容
     * @param width
     *            宽
     * @param height
     *            高
     * @param imageFormat
     *            图片类型
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static boolean encode(OutputStream outputStream, String content,
            int width, int height, String imageFormat) throws WriterException,
        IOException {
        // 1.

        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        // 创建比特矩阵(位矩阵)的QR码编码的字符串
        BitMatrix byteMatrix = qrCodeWriter.encode(content,
                BarcodeFormat.QR_CODE, width, height, getDecodeHintType());
        // 2.
        BufferedImage image = toBufferedImage(byteMatrix);

        return ImageIO.write(image, imageFormat, outputStream);
    }

    /**
     * 
     * @description 生成有logo的二维码图片
     * @author lli
     * @create 2017年7月31日上午11:08:39
     * @version 1.0
     * @param outputStream
     *            文件输出流
     * @param content
     *            内容
     * @param width
     *            宽
     * @param height
     *            高
     * @param imageFormat
     *            图片类型
     * @param logoPic
     *            logo图片
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static void encodeWithLogo(OutputStream outputStream,
            String content, int width, int height, String imageFormat,
            File logoPic) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        // 创建比特矩阵(位矩阵)的QR码编码的字符串
        BitMatrix byteMatrix = qrCodeWriter.encode(content,
                BarcodeFormat.QR_CODE, width, height, getDecodeHintType());
        BufferedImage image = toBufferedImage(byteMatrix);
        addLogo(outputStream, image, logoPic);
    }

    /**
     * 
     * @description 解析二维码内容
     * @author lli
     * @create 2017年7月31日上午11:09:55
     * @version 1.0
     * @param inputStream
     *            文件输入流
     * @throws IOException
     */
    public static void decode(InputStream inputStream) throws IOException {
        // 从输入流中获取字符串信息
        BufferedImage image = ImageIO.read(inputStream);
        // 将图像转换为二进制位图源
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        QRCodeReader reader = new QRCodeReader();
        Result result = null;
        try {
            result = reader.decode(bitmap);
            System.out.println(result.getText());
        } catch (ReaderException e) {
            e.printStackTrace();
        }

    }

    /**
     * 
     * @description 设置二维码的格式参数
     * @author lli
     * @create 2017年7月31日上午11:31:20
     * @version 1.0
     * @return
     */
    private static Map<EncodeHintType, Object> getDecodeHintType() {
        // 用于设置QR二维码参数
        Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
        // 设置QR二维码的纠错级别（H为最高级别）具体级别信息
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 设置编码方式
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        // 设置二维码边的空度，非负数
        hints.put(EncodeHintType.MARGIN, 0);

        return hints;
    }

    private static void addLogo(OutputStream outputStream, BufferedImage image,
            File logoPic) throws IOException {

        /**
         * 读取二维码图片，并构建绘图对象
         */
        Graphics2D g = image.createGraphics();

        /**
         * 读取Logo图片
         */
        BufferedImage logo = ImageIO.read(logoPic);
        /**
         * 设置logo的大小,本人设置为二维码图片的20%,因为过大会盖掉二维码
         */
        int widthLogo = logo.getWidth(null) > image.getWidth() * 2 / 10 ? (image
                .getWidth() * 2 / 10) : logo.getWidth(null), heightLogo = logo
                .getHeight(null) > image.getHeight() * 2 / 10 ? (image
                .getHeight() * 2 / 10) : logo.getHeight(null);

        // 计算图片放置位置
        /**
         * logo放在中心
         */
        int x = (image.getWidth() - widthLogo) / 2;
        int y = (image.getHeight() - heightLogo) / 2;
        /**
         * logo放在右下角
         */
        // int x = (image.getWidth() - widthLogo);
        // int y = (image.getHeight() - heightLogo);
        // 开始绘制图片
        g.drawImage(logo, x, y, widthLogo, heightLogo, null);
        g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
        BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND,
                BasicStroke.JOIN_ROUND);
        g.setStroke(stroke);
        g.setColor(Color.GRAY);
        g.drawRect(x, y, widthLogo, heightLogo);

        g.dispose();
        logo.flush();
        image.flush();

        ImageIO.write(image, "JPEG", outputStream);

    }

    private static BufferedImage toBufferedImage(BitMatrix byteMatrix) {
        int width = byteMatrix.getWidth();
        int height = byteMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, (byteMatrix.get(x, y) ? Color.BLUE.getRGB()
                        : Color.WHITE.getRGB()));
            }
        }
        return image;
    }

}